<?php


namespace lib\model;
use lib\basic\PdoTool;


class Model {
    protected $db = null;
    protected $__fields = []; //字段名
    protected $__dirty = []; //有变动的字段和值
    protected $__asArray = false;
    /** @var \lib\model\Query  */
    public $query = null; //query 对象

    /** @var array 该表含有的字段 */
    public static $fields = [];
    /** @var string 表名 */
    public static $table = "";
    /** @var string 主键名 */
    public static $primaryKey = "";

    public function __construct($attrs = []) {
        $this->db = PdoTool::getPdo();

        if (!static::$fields) {
            $table = static::$table;
            $sql = "select COLUMN_NAME from information_schema.COLUMNS where table_name = '{$table}'";
            $sth = $this->db->query($sql);
            if (!$sth) throw new \Exception("query {$sql} error", 2);
            $result = $sth->fetchAll(\PDO::FETCH_ASSOC);
            if (!$result) throw new \Exception("query {$sql} no result", 2);
            foreach ($result as $row) {
                static::$fields [] = $row['COLUMN_NAME'];
            }
        }

        $this->setAttributes($attrs);
    }

    /**
     * @param $name
     * @return mixed|string
     */
    public function __get($name) {
        return $this->__fields[$name] ? $this->__fields[$name] : "";
    }

    /**
     * @param $name
     * @param $value
     */
    public function __set($name, $value) {
        // TODO: Implement __set() method.
        $this->__fields[$name] = $value;
        if ($name != static::$primaryKey)
            $this->__dirty[$name] = $value;
    }

    /**
     * 更新
     * @param $attrs
     * @param $conds
     * @return int
     */
    public static function updateAll ($attrs, $conds) {
        $query = new Query();
        $sql = $query->where($conds)->set($attrs)->update(static::$table);
        return PdoTool::getPdo()->exec($sql);
    }

    /**
     * 删除
     * @param $conds
     * @return int
     */
    public static function deleteAll ($conds) {
        $query = new Query();
        $sql = $query->where($conds)->delete(static::$table);
        return PdoTool::getPdo()->exec($sql);
    }

    /**
     * @return Model
     * @throws \Exception
     */
    public static function find () {
        $model = new static();
        $model->query = new Query();
        return $model;
    }

    /**
     * @param $conds
     * @return $this
     */
    public function where ($conds) {
        $this->query->where($conds);
        return $this;
    }

    /**
     * @param $conds
     * @return $this
     */
    public function andWhere ($conds) {
        $this->query->andWhere($conds);
        return $this;
    }

    /**
     * @param $conds
     * @return $this
     */
    public function orWhere ($conds) {
        $this->query->orWhere($conds);
        return $this;
    }

    /**
     * @param $fields
     * @return $this
     */
    public function fields ($fields) {
        $this->query->fields($fields);
        return $this;
    }

    /**
     * @param $offset
     * @param null $rows
     * @return $this
     */
    public function limit ($offset, $rows = null) {
        $this->query->limit($offset, $rows);
        return $this;
    }

    /**
     * @param string $orderBy
     * @return $this
     */
    public function orderBy ($orderBy = "") {
        $this->query->orderBy($orderBy);
        return $this;
    }

    /**
     *
     */
    public function one () {
        $sql = $this->query->from(static::$table)->select();
        $sth = $this->db->query($sql);
        if (!$sth) return null; //TODO:使用find()时new static()产生的对象未释放问题
        $row = $sth->fetch(\PDO::FETCH_ASSOC);
        if (!$row) return null;
        $this->setAttributes($row);
        if ($this->__asArray) {
            return $this->getAttributes();
        } else {
            return $this;
        }
    }

    /**
     * @return array|null
     * @throws \Exception
     */
    public function all () {
        $sql = $this->query->from(static::$table)->select();
        $sth = $this->db->query($sql);
        if (!$sth) return null; //TODO:使用find()时new static()产生的对象未释放问题
        $rows = $sth->fetchAll(\PDO::FETCH_ASSOC);
        if (!$rows) return null;

        $result = [];
        foreach ($rows as $row) {
            if ($this->__asArray) {
                $result[] = $row;
            } else {
                $result[] = new static($row);
            }
        }

        return $result;
    }

    /**
     * @return array
     */
    public function getAttributes() {
        return $this->__fields;
    }

    /**
     * @param array $attrs
     */
    public function setAttributes ($attrs = []) {
        foreach ($attrs as $key => $value) {
            if (in_array($key, static::$fields))
                $this->__fields[$key] = $value;
        }
    }

    /**
     * @return $this
     */
    public function asArray() {
        $this->__asArray = true;
        return $this;
    }

    /**
     * @return array
     */
    public function toArray () {
        return $this->getAttributes();
    }

    /**
     * @return int
     */
    public function save () {
        $query = new Query();
        $primaryKey = static::$primaryKey;
        if (!array_key_exists($primaryKey, $this->__fields)) {
            //insert
            $sql = $query->insert(static::$table, $this->__fields);
            $res = $this->db->exec($sql);
            if (!$res) return false;
            $this->__fields[$primaryKey] = $this->db->lastInsertId();
        } else {
            //update
            if (!$this->__dirty) return true;

            $sql = $query->where(["{$primaryKey}" => $this->__fields[$primaryKey]])->set($this->__dirty)->update(static::$table);
            $this->__dirty = []; //clear dirty data
            return $this->db->exec($sql);
        }
    }



//    public function
}